package com.inspur.edp.ai.flow.core.engine;

import com.inspur.edp.ai.flow.exception.FlowException;
import com.inspur.edp.ai.flow.metadata.json.*;
import com.inspur.edp.common.expr.constant.ExpressConstant;
import com.inspur.edp.common.type.Field;
import com.inspur.edp.common.type.Type;
import com.inspur.edp.common.type.TypeRefer;
import com.inspur.edp.common.type.constant.TypeConstant;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lizhaorui
 * @date 2025/9/15
 * @description
 */
public class JsonTypeMgr {

    public static ConvertResult convert(String typePrefix, JsonType jsonType) {
        List<Type> types = new ArrayList<>();
        ConvertResult convertResult = new ConvertResult();
        convertResult.setTypes(types);
        if (jsonType instanceof JsonObjectType) {
            Type objectType = convertObjectType(typePrefix, types, (JsonObjectType) jsonType);
            convertResult.setRootType(new TypeRefer(objectType.getSource(), objectType.getTypeId()));
            return convertResult;
        } else if (jsonType instanceof JsonArrayType) {
            TypeRefer arrayTypeRefer = convertArrayTypeRefer(typePrefix, types, (JsonArrayType) jsonType);
            convertResult.setRootType(arrayTypeRefer);
            return convertResult;
        } else {
            throw new FlowException("not support convert to typeRefer");
        }
    }

    @Data
    public static class ConvertResult {
        private TypeRefer rootType;
        private List<Type> types;
    }

    private static TypeRefer convertArrayTypeRefer(String typePrefix, List<Type> types, JsonArrayType jsonArrayType) {
        JsonType jsonItemType = jsonArrayType.getItems();
        Type itemType = convertObjectType(typePrefix + "_item", types, (JsonObjectType) jsonItemType);

        Type type = new Type();
        type.setSource(TypeRefer.JSON_SCHEMA_SOURCE);
        type.setTypeOptCode("com.fasterxml.jackson.databind.node.ArrayNode");
        type.setTypeId(typePrefix);
        type.setArrayAccessKind(ExpressConstant.JSON_ARRAY_ACCESS_KIND);
        types.add(type);

        TypeRefer typeRefer = new TypeRefer(type.getSource(), type.getTypeId());
        typeRefer.setGenericTypes(new ArrayList<>());
        typeRefer.getGenericTypes().add(new TypeRefer(itemType.getSource(), itemType.getTypeId()));
        return typeRefer;
    }

    private static Type convertObjectType(String typePrefix, List<Type> types, JsonObjectType jsonObjectType) {
        Type type = new Type();
        type.setSource(TypeRefer.JSON_SCHEMA_SOURCE);
        type.setTypeOptCode("com.fasterxml.jackson.databind.node.ObjectNode");
        type.setTypeId(typePrefix);
        types.add(type);
        type.setFields(new ArrayList<>());
        List<JsonObjectProperty> properties = jsonObjectType.getProperties();
        for (JsonObjectProperty property : properties) {
            Field field = new Field();
            field.setCode(property.getCode());
            String newTypePrefix = String.format("%s_%s", typePrefix, property.getCode());
            TypeRefer fieldType = convertPropertyTypeRefer(newTypePrefix, types, property.getType());
            field.setType(fieldType);
            field.setAccessKind(TypeConstant.JSON);
            type.getFields().add(field);
        }
        return type;
    }

    private static TypeRefer convertPropertyTypeRefer(String typePrefix, List<Type> types, JsonType propertyType) {
        if (propertyType instanceof JsonStringType) {
            return TypeRefer.STRING_TYPE;
        } else if (propertyType instanceof JsonNumberType) {
            return TypeRefer.NUMBER_TYPE;
        } else if (propertyType instanceof JsonBooleanType) {
            return TypeRefer.BOOLEAN_TYPE;
        } else if (propertyType instanceof JsonObjectType) {
            Type objectType = convertObjectType(typePrefix, types, (JsonObjectType) propertyType);
            return new TypeRefer(objectType.getSource(), objectType.getTypeId());
        } else if (propertyType instanceof JsonArrayType) {
            return convertArrayTypeRefer(typePrefix, types, (JsonArrayType) propertyType);
        } else {
            throw new FlowException("not support convert to typeRefer");
        }
    }

}